package com.mamingchao.springcloud.eureka.controller;

import com.mamingchao.springcloud.eureka.api.*;
import com.mamingchao.springcloud.eureka.util.JsonMapper;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.QueryParam;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Created by mamingchao on 2020/8/21.
 */
@RestController
@RefreshScope
public class ClientTestController {

    @Autowired
    private DiscoveryClient client;

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @Autowired
    RestTemplate restTemplate;

    @Autowired
    ProviderApi providerApi;

    @Autowired
    ProviderApi1 providerApi1;

    @Autowired
    ProviderApi2 providerApi2;

    @Autowired
    ProviderApi3 providerApi3;

    @Autowired
    ProviderApi4 providerApi4;

    @Autowired
    BusiService  service;

    @Value("${myconfig}")
    private String myconfig;

    @GetMapping("/client1")
    public String client1() {

        List<String> services = client.getServices();

        return JsonMapper.INSTANCE.toJson(services);
    }

    @GetMapping("/client2")
    public String client2(@QueryParam("instanceName") String instanceName,@QueryParam("uriPath") String uriPath) {

        List<ServiceInstance> instances = client.getInstances(instanceName);

        String url ="http://";
        for (ServiceInstance item:instances) {
            System.out.println("uri: " + item.getUri());
            System.out.println("host: " + item.getHost());
            System.out.println("instanceId: " + item.getInstanceId());
            System.out.println("port: " + item.getPort());
            System.out.println("serviceId: " + item.getServiceId());
            System.out.println("schema: " + item.getScheme());
//            url = url + item.getHost() +":" + item.getPort() + "/" + uriPath;
            url = item.getUri()+ "/" + uriPath;

            System.out.println(url);
        }

        return url;
    }

    @GetMapping("/client3")
    public String client3(@QueryParam("instanceName") String instanceName,@QueryParam("uriPath") String uriPath) {

        List<ServiceInstance> instances = client.getInstances(instanceName);

        String url = instances.get(0).getUri()+ "/" + uriPath;

        RestTemplate restTemplate = new RestTemplate();

        String object = restTemplate.getForObject(url, String.class);
        return object;
    }

    @GetMapping("/client4")
    public String client4(@QueryParam("instanceName") String instanceName,@QueryParam("uriPath") String uriPath) {

        ServiceInstance instance = loadBalancerClient.choose(instanceName);

        String url = instance.getUri()+ "/" + uriPath;

        RestTemplate restTemplate = new RestTemplate();

        String object = restTemplate.getForObject(url, String.class);
        return object;
    }

    @GetMapping("/client5")
    public String client5() {

        String url = "http://serviceProvider/getHi";

        return restTemplate.getForObject(url, String.class);
    }

    @GetMapping("/client6")
    public void client6(String name, HttpServletResponse resp) throws Exception {

        String url = "http://localhost:8080/postLocation";

        Map param = Collections.singletonMap("keyword", name);

        URI uri = restTemplate.postForLocation(url, param);

        resp.sendRedirect(uri.toString());
    }


    /**
     * 不集成Eureka 单独使用feign
     * 当 httpClient使用
     * @return
     * @throws Exception
     */
    @GetMapping("/client7")
    public String client7() throws Exception {

        return providerApi.getHiProxy();
    }

    /**
     * 集成Eureka 使用feign
     * @return
     * @throws Exception
     */
    @GetMapping("/client8")
    public String client8() throws Exception {
        return providerApi1.getHiProxy();
    }

    /**
     * 集成 Eureka ribbon feign
     * java 调用java 非异构平台
     * @return
     * @throws Exception
     */
    @GetMapping("/client9")
    public String client9(String name) throws Exception {
        return providerApi2.hello("muxiaolin");
    }

    /**
     * 集成 Eureka ribbon feign
     * java 调用java 非异构平台
     * @return
     * @throws Exception
     */
    @GetMapping("/client10")
    public String client10() throws Exception {
        return providerApi2.greeting();
    }


    /**
     * 集成 Eureka ribbon feign
     * java 调用java 非异构平台
     * 测试ribbon read timeout
     * 以及 当其中一个provider readtimeout 发生后，ribbon的处理机制
     * @return
     * @throws Exception
     */
    @GetMapping("/client11")
    public String client11() throws Exception {
        return providerApi2.ribbonReadTimeoutTest();
    }

    /**
     * 测试 通过 feignClient fallback 方式
     *
     * @return
     * @throws Exception
     */
    @GetMapping("/client12")
    public String client12(String name) throws Exception {
        return providerApi3.hello(name);
    }

    /**
     * 测试 通过 feignClient fallbackFactory 方式
     *
     * @return
     * @throws Exception
     */
    @GetMapping("/client13")
    public String client13(String name) throws Exception {
        return providerApi4.hello(name);
    }

    /**
     * 测试 通过 feignClient fallbackFactory 方式
     *
     * @return
     * @throws Exception
     */
    @GetMapping("/client14")
    public String client14(String name) throws Exception {
        return service.helloProcessLogic();
    }


    /**
     * 测试从 spring cloud config 获取 配置
     *
     * @return
     * @throws Exception
     */
    @GetMapping("/client15")
    public String client15() throws Exception {
        return myconfig;
    }


}
